home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sources.misc
- subject: v08i064: bug -- make a transcript of a socket connection
- from: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Reply-To: matthew@CS.UCLA.EDU (Matthew Merzbacher)
-
- Posting-number: Volume 8, Issue 64
- Submitted-by: matthew@CS.UCLA.EDU (Matthew Merzbacher)
- Archive-name: bug
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # README
- # bug.1
- # bug.c
- # This archive created: Fri Sep 29 18:29:52 1989
- export PATH; PATH=/bin:$PATH
- if test -f 'README'
- then
- echo shar: will not over-write existing file "'README'"
- else
- cat << \SHAR_EOF > 'README'
- Bug is used to tap a stream socket. It is useful for tracing communication
- between a server and its clients. The communication between server and
- client is maintained while transcripts of all communication lines are taken.
-
- There is a man page (bug.1), a source file (bug.c) and this file (README)
- included in this archive. No Makefile is necessary, since to "make" it, all
- you do is:
- cc -o bug bug.c
-
- You need to be running a BSD or BSD-derived system (since it examines sockets).
- It has been tested under SunOS 4.0.3
-
- If you don't like my MARK, you can change it by changing the lines
- #define MARK
- and
- #define MARKLEN
- to your own values.
-
- I'd be interested in hearing what people have to say and what they use 'bug'
- for. I hope I haven't re-invented the wheel. Bugs/Comments/Questions/Hate
- Mail to me,
-
- Matthew Merzbacher ARPA: matthew@CS.UCLA.EDU
- UUCP: ...!{uunet|rutgers|ucbvax}!cs.ucla.edu!matthew
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'bug.1'
- then
- echo shar: will not over-write existing file "'bug.1'"
- else
- cat << \SHAR_EOF > 'bug.1'
- .TH BUG 1
- \" Copyright (C) 1989 by Matthew Merzbacher. All Rights Reserved.
- .SH NAME
- bug \- listen and transcribe communication on a socket
- .SH SYNOPSIS
- .B bug
- .nh
- input_port output_port machine client_file server_file
- .hy
- .SH DESCRIPTION
- .I bug
- is used to listen on a specified \fIinput_port\fR and write an exact
- duplicate out to the \fIoutput_port\fR on a specified \fImachine\fR. It
- also writes a transcript of everything that is said on either port
- to seperate files. Each piece of communication is seperated by a MARK, which
- is #defined in the code as "<MARK>".
- .PP
- The naming scheme for the output files is \fIclient_file\fR (for communication
- received from the \fIinput_port\fR) or \fIserver_file\fR (for communication
- received from the \fIoutput_port\fR) followed by a period ('.') followed by
- the process id of the bug program followed by a period ('.') followed by the
- process id of the child of bug which actually does the monitoring. Thus, for
- every connection made to the input_port, there will be two (unique) files
- created.
- .PP
- The output files are probably best read by using \fIod\fR(1) with the "-c"
- or "-cx" options.
- .SH EXAMPLE
- \fIbug\fR 3000 2999 moosebreath cl se
- .PP
- This invocation will create, for every connection to port 3000 on the current
- machine, two files (cl.pid.cpid and se.pid.cpid). Every communication to port
- 3000 is repeated verbatim to port 2999 on machine "moosebreath" and written to
- the first file. All responses are written to the second file.
- .SH FILES
- .br
- creates files based on \fIclient_file\fR and \fIserver_file\fR
- .SH "SEE ALSO"
- od(1), socket(2) [and friends], fork(2).
- .SH AUTHOR
- Matthew Merzbacher, bugs/comments - matthew@cs.ucla.edu
- .SH BUGS
- .PP
- Goodness knows what systems this will actually run on. Any BSD or
- BSD-derived system SHOULD work.
-
- There should be an option to change the MARK.
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'bug.c'
- then
- echo shar: will not over-write existing file "'bug.c'"
- else
- cat << \SHAR_EOF > 'bug.c'
- /* Copyright (C) 1989 by Matthew Merzbacher.
- All Rights Reserved.
- Bug is provided as is, without express or implied warranty. In no event
- shall Matthew Merzbacher become liable for any loss or damages, consequential
- or otherwise, arising from the use or possession of this software.
- */
-
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <stdio.h>
- #include <fcntl.h>
-
- #define MARK "<MARK>"
- #define MARKLEN 6
-
- /*
- * Brief Description:
- * Bug is used to tap a stream socket. It is useful for tracing communication
- * between a server and its clients. The communication between server and
- * client is maintained while transcripts of all communication lines are taken.
- * It has six required (and no optional) arguments.
- *
- * Usage:
- * bug <in port> <out port> <machine> <client file> <server file>
- *
- * <in port> - the port (on the machine on which bug runs) to which to
- * clients will connect (the pseudo-port)
- * <out port> - the true server port
- * <machine> - the server machine
- * <client file> - transcript file of what each client says
- * <server file> - transcript file of what the server responds
- *
- * Example:
- * Suppose a server listens on port 3000 of machine "xyz". The user must
- * artificially make the clients talk to some other port (on any machine -
- * it could be the server machine, the client machine, or a third machine).
- * That port is called the pseudo-port. Bug runs on the machine of the
- * pseudo-port. To run it, type:
- *
- * bug 2999 3000 xyz client server
- *
- * This assumes that the pseudo-port is 2999. The output files will all start
- * with "client" or "server" followed by the process number of the bug process
- * and the process number of each seperate listening session. That way, you
- * can follow the connection order. Typically, the output files created by bug
- * may be read by using 'od -c'.
- *
- */
-
- main(argc, argv)
- int argc; char *argv[];
- {
- struct sockaddr_in server;
- struct hostent *hp, *gethostbyname();
- char buf[1024];
- int rval;
- int outfile1, outfile2;
- int insock, outsock, msgsock;
- int insocknum, outsocknum;
- fd_set fdset;
-
-
- /* Check Arguments */
-
- if (argc < 6) {
- printf("usage: %s <in port> <out port> <machine> <client file> <server file>\n",argv[0]);
- exit(1);
- }
-
- insocknum = atoi(argv[1]);
- outsocknum = atoi(argv[2]);
-
-
- /* Create listening post on pseudo-port */
-
- insock = socket(AF_INET, SOCK_STREAM, 0);
-
- if (insock < 0) {
- perror("opening pseudo-port stream socket");
- exit(1);
- }
-
-
- /* Name socket using user supplied port number */
-
- server.sin_family = AF_INET;
- server.sin_addr.s_addr = INADDR_ANY;
- server.sin_port = insocknum;
-
- if (bind(insock, &server, sizeof(server))) {
- perror("binding pseudo-port stream socket");
- exit(1);
- }
-
-
- /* Start accepting connections */
-
- listen(insock, SOMAXCONN);
-
-
- /* Every connection spawns a child to handle the communication */
-
- do {
- msgsock = accept(insock, 0, 0);
- if (msgsock == -1)
- perror("accept");
- } while (fork() != 0);
-
-
- /* Close listening post - it's now called "msgsock" */
-
- close(insock);
-
-
- /* Create output socket to server */
-
- outsock = socket(AF_INET, SOCK_STREAM, 0);
- if (outsock < 0) {
- perror("opening server stream socket");
- exit(1);
- }
-
-
- /* Connect socket using machine & port specified on command line. */
-
- server.sin_family = AF_INET;
- hp = gethostbyname(argv[3]);
- if (hp == 0) {
- fprintf(stderr, "%s: unknown machine\n", argv[3]);
- exit(2);
- }
-
- bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
- server.sin_port = htons(outsocknum);
-
- if (connect(outsock, &server, sizeof(server)) < 0) {
- perror("connecting server stream socket");
- exit(1);
- }
-
-
- /* Open the output files */
-
- sprintf(buf,"%s.%d.%d",argv[4],getppid(),getpid());
- if ((outfile1 = open(buf, O_TRUNC|O_WRONLY|O_CREAT, 0644)) == -1) {
- fprintf(stderr,"cannot open file: %s\n",buf);
- exit(1);
- }
-
- sprintf(buf,"%s.%d.%d",argv[5],getppid(),getpid());
- if ((outfile2 = open(buf, O_TRUNC|O_WRONLY|O_CREAT, 0644)) == -1) {
- fprintf(stderr,"cannot open file: %s\n",buf);
- exit(1);
- }
-
- do {
-
- /* find out who's talking */
-
- FD_ZERO(&fdset);
- FD_SET(msgsock, &fdset);
- FD_SET(outsock, &fdset);
- if (select(getdtablesize(), &fdset, 0, 0, 0) == -1) {
- perror("select");
- exit(1);
- }
- bzero(buf, 1024);
-
- if (FD_ISSET(msgsock, &fdset) && FD_ISSET(outsock, &fdset))
- fprintf(stderr,"Two talkers - no listeners\n");
-
-
- /* Client is talking to server */
-
- if (FD_ISSET(msgsock, &fdset)) {
- if ((rval = read(msgsock, buf, 1024)) < 0)
- perror("reading stream message");
- if (rval == 0)
- fprintf(stderr,"Ending client connection\n");
- else {
- write(outfile1, buf, rval);
- write(outfile1, MARK, 6);
- if (write(outsock, buf, rval) < 0)
- perror("writing on output stream socket");
- }
- }
-
- /* Server is talking to client */
-
- else {
- if (! FD_ISSET(outsock, &fdset)) {
- perror("weird behavior");
- exit(1);
- }
- if ((rval = read(outsock, buf, 1024)) < 0)
- perror("reading stream message");
- if (rval == 0)
- fprintf(stderr,"Ending server connection\n");
- else {
- write(outfile2, buf, rval);
- write(outfile2, MARK, 6);
- if (write(msgsock, buf, rval) < 0)
- perror("writing on output stream socket");
- }
- }
- } while (rval != 0);
-
-
- /* Close up shop */
-
- fprintf(stderr, "Closing Connections\n");
- close(msgsock);
- close(outsock);
- close(outfile1);
- close(outfile2);
- }
- SHAR_EOF
- fi # end of overwriting check
- # End of shell archive
- exit 0
-